package src.edu.wayne.cs.csc4110.hw6.implementations;

import java.util.ArrayList;
import java.util.HashSet;

import javax.swing.JPanel;

import src.edu.wayne.cs.csc4110.hw6.implementations.dbase.FacelookDatabaseImpl;
import src.edu.wayne.cs.csc4110.hw6.implementations.stateMachine.StateMachine;
import src.edu.wayne.cs.csc4110.hw6.interfaces.FacelookDatabase;
import src.edu.wayne.cs.csc4110.hw6.interfaces.Game;
import src.edu.wayne.cs.csc4110.hw6.interfaces.FrameWork;
import src.edu.wayne.cs.csc4110.hw6.interfaces.GameUser;
import src.edu.wayne.cs.csc4110.hw6.interfaces.PluginToFrameWorkInterface;
import src.edu.wayne.cs.csc4110.hw6.interfaces.State;
import src.edu.wayne.cs.csc4110.hw6.interfaces.User;

public class FrameWorkImpl implements FrameWork, PluginToFrameWorkInterface {

	private static FrameWork frameWork; 
	private static State stateMachine;
	
	private HashSet<User> usersInSession;
	private FacelookDatabase dataBase;
	private Game plugin;
	private ArrayList<Game> gameList;
	private VideoFrameImpl displayFrame;
	
	
	public synchronized static FrameWork getFrameWork() {
		if (frameWork == null)
		{
			frameWork = new FrameWorkImpl();
			
		}
		return frameWork;
	}
	
	private FrameWorkImpl()	{
		this.setDataBase(new FacelookDatabaseImpl());
		setUsersInSession(new HashSet<User>());
		stateMachine = new StateMachine(this);	
		displayFrame = VideoFrameImpl.getVideoFrame();
	}
	
	@Override
	public FacelookDatabase getDataBase() {
		return dataBase;
	}

	public void setDataBase(FacelookDatabase dataBase) {
		this.dataBase = dataBase;
	}

	@Override
	public void startFrameWork() {
		stateMachine.goToLoggedInState();
	}
	
	/**
	 * Used for debug
	 * @param user
	 */
	public void setCurrentUser(User user){
		if (FrameWorkImpl.stateMachine instanceof StateMachine)
		{
			((StateMachine) stateMachine).setCurrentUser(user);
		}
	}
	
	/**
	 * for debug
	 * @return State
	 */
	public StateMachine getStateMachine()
	{
		return (StateMachine) stateMachine;
	}
	
	/** 
	 * for debug
	 * @param state
	 */
	public void setState(State state){
		if (FrameWorkImpl.stateMachine instanceof StateMachine)
		{
			((StateMachine) stateMachine).setState(state);
		}
	}

	@Override
	public Game getPlugin() {
		return plugin;
	}

	@Override
	public void setPlugin(Game plugin) {
		this.plugin = plugin;
	}
	
	@Override
	public void addUserToSession(User user){
		usersInSession.add(user);
	}

	@Override
	public HashSet<User> getUsersInSession() {
		return usersInSession;
	}
	
	/**
	 * Returns a set of the current users to the plugin.
	 * @return HashSet<GameUser>
	 */
	public HashSet<GameUser> getPlayersInSession(){
		HashSet<GameUser> gameUsers = new HashSet<GameUser>();
		for (User user: usersInSession){
			if (user != null){
				GameUser newUser = (GameUser) user;
				gameUsers.add(newUser);
			}
		}
		return gameUsers;
	}
	
	@Override
	public boolean isUserInCurrentSession(User user)
	{
		return this.usersInSession.contains(user);
	}

	@Override
	public void setUsersInSession(HashSet<User> usersInSession) {
		this.usersInSession = usersInSession;
	}

	@Override
	public ArrayList<Game> getGameList() {
		return this.gameList;
	}

	/**
	 * Added to allow plugins to be added in a less than
	 * elegant fashion.
	 * @param games
	 */
	public void setGameList(ArrayList<Game> games) {
		this.gameList = games;
	}
	
	@Override
	public void setCurrentPanel(JPanel newPanel, String newTitle) {
		displayFrame.setCurrentPanel(newPanel, newTitle);
	}

	@Override
	public void removeUserFromSession(User user) {
		if (usersInSession.contains(user)){
			usersInSession.remove(user);
		}
		
		
	}

	@Override
	public void endGame() {
		stateMachine.goToLoggedInState();
	}

	@Override
	public boolean login(String email, String pwd) {
		return dataBase.login(email, pwd);
	}

}
